<script setup lang="ts">
import { ref, defineExpose } from "vue"
import { Edge, NodeChange, Position, VueFlow, useVueFlow, NodeMouseEvent } from "@vue-flow/core"
import { MiniMap } from "@vue-flow/minimap"
import ParamSetting from "./ParamSetting.vue"
import { ElMessage, ElMessageBox } from "element-plus"
import useDragAndDrop from "@@/composables/useDragAndDrop"
import { Sidebar, DropzoneBackground } from "./index"
import { FormTypeEnum } from "@/common/constants/other-keys"
import { EditInfrenceBasicInfo } from "@/common/apis/train/type"
import { Edit } from "@element-plus/icons-vue"
import { cloneDeep } from "lodash"
import { updateTaskApi } from "@/common/apis/train"

interface Props {
  dialogType: FormTypeEnum
  ruleForm: EditInfrenceBasicInfo
}
const props = defineProps<Props>()
const emit = defineEmits(["update:ruleForm"])

const isEdit = ref<boolean>(false)
const tempForm = ref<EditInfrenceBasicInfo | null>(null)
const { onInit, onConnect, onNodesChange, applyNodeChanges } = useVueFlow()
const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()

const drawerVisible = ref<boolean>(false)
const curId = ref<string | undefined>(undefined)
const delId = ref<string | undefined>(undefined)
// 存储数据采集节点的id数组
const collectionNodes = ref<string[]>([])

const edges = ref<Edge[]>([])
const dark = ref(false)
const connectedNodeIds = ref<string[]>([])

onInit((vueFlowInstance) => {
  vueFlowInstance.fitView({ maxZoom: 1.5 })
})

onConnect((params) => {
  const edge = {
    id: `e-${params.source}-${params.target}`,
    source: params.source,
    target: params.target,
    // type: "smoothstep"
  }
  edges.value.push(edge)
})

onNodesChange(async (changes: NodeChange[]) => {
  const nextChanges: NodeChange[] = []
  for (const change of changes) {
    if (change.type === "remove") {
      if (change.id == "1") {
        ElMessage.warning("不可以删除该节点！")
        return
      }
      const isConfirmed = await dialogMsg(change.id)

      if (isConfirmed) {
        nextChanges.push(change)
      }
    } else {
      nextChanges.push(change)
    }
  }
  applyNodeChanges(nextChanges)
})

function dialogMsg(label: string) {
  return new Promise((resolve) => {
    ElMessageBox.confirm(`确定是否要删除${label}？`, "提示", {
      confirmButtonText: "删除",
      cancelButtonText: "取消",
      type: "warning"
    })
      .then(() => {
        resolve(true)
      })
      .catch(() => {
        resolve(false)
      })
  })
}
const onDropOver = (event: DragEvent) => {
  onDrop(event)
}
// 关闭抽屉
const handleCloseDrawer = () => {
  curId.value = undefined
  drawerVisible.value = false
}
const handleClickNode = (name: string, event) => {
  const { node } = event
  if (node.type !== "input") {
    curId.value = node.id
    delId.value = node.id
    // 获取与当前节点相连的所有边
    const connectedEdges = edges.value.filter((edge) => edge.target === node.id || edge.source === node.id)
    // 获取相连节点的ID（排除当前节点）
    connectedNodeIds.value = connectedEdges
      .map((edge) => (edge.source === node.id ? edge.target : edge.source))
      .filter((id) => id !== node.id)
    drawerVisible.value = true
  }
}
function onDragStop(event: NodeMouseEvent) {
  const { node } = event
  if (node.type !== "input") {
    delId.value = node.id
  }
}
// Store initial form data when entering edit mode
function handleEdit() {
  tempForm.value = cloneDeep(props.ruleForm)
  isEdit.value = true
}

// Cancel save handler
function handleCancelSave() {
  if (tempForm.value) {
    Object.keys(props.ruleForm).forEach((key) => {
      props.ruleForm[key] = tempForm.value[key]
    })
  }
  isEdit.value = false
  tempForm.value = null
}

// Save handler
async function handleSave() {
  await updateTaskApi(props.ruleForm)
  isEdit.value = false
  tempForm.value = null
  ElMessage.success("保存成功")
}

const localRuleForm = computed({
  get: () => {
    const newNodes = props.ruleForm.data_collections.data_nodes_info
    // 重新计算 collectionNodes
    collectionNodes.value = newNodes
      .filter(node => node.type === "default" && node.id !== "1")
      .map(node => node.id)

    // 找到导出结果节点
    const outputNode = newNodes.find(node => node.id === "9999")

    // 重置边
    edges.value = []

    // 先添加与节点1的连线
    newNodes.forEach((item) => {
      if (item.id !== "1" && item.type === "default") {
        item.targetPosition = Position.Left
        item.sourcePosition = Position.Right
        edges.value.push({
          id: `e-1-${item.id}`,
          source: "1",
          target: item.id,
          // type: "smoothstep"
        })
      }
    })

    // 如果有导出结果节点，添加与数据采集节点的连线
    if (outputNode) {
      outputNode.targetPosition = Position.Left
      collectionNodes.value.forEach((collectionNodeId) => {
        edges.value.push({
          id: `e-${collectionNodeId}-${outputNode.id}`,
          source: collectionNodeId,
          target: outputNode.id,
          // type: "smoothstep"
        })
      })
    }
    return props.ruleForm
  },
  set: (newValue) => {
    emit("update:ruleForm", newValue)
  }
})

// 暴露验证方法给父组件
defineExpose({
  validate: async () => {
    return true
  }
})
</script>

<template>
  <div class="dnd-flow" @drop="onDropOver">
    <div class="cpi-header">
      <span class="cpi-header-text">数据采集</span>
    </div>
    <Sidebar v-if="isEdit || dialogType == FormTypeEnum.CREATE" :id="delId" />
    <VueFlow
      v-model:nodes="localRuleForm.data_collections.data_nodes_info"
      :edges="edges"
      :class="{ dark }"
      :apply-default="false"
      :elevate-edges-on-select="true"
      class="basic-flow"
      @node-drag-stop="onDragStop"
      @dragover="onDragOver"
      @dragleave="onDragLeave"
      @node-click="handleClickNode('click', $event)"
    >
      <DropzoneBackground
        :style="{
          backgroundColor: isDragOver ? '#001b44' : 'transparent',
          transition: 'background-color 0.2s ease'
        }"
      >
        <p v-if="isDragOver">拖拽到这里</p>
      </DropzoneBackground>
      <MiniMap />
    </VueFlow>

    <ParamSetting
      v-if="dialogType === FormTypeEnum.VIEW && !isEdit"
      :id="curId"
      :visible="drawerVisible"
      :connected-nodes="connectedNodeIds"
      @close-dialog="handleCloseDrawer"
    />
  </div>
</template>
<style lang="scss" scoped>

.vue-flow__minimap {
  transform: scale(75%);
  transform-origin: bottom right;
}

.dnd-flow {
  width: 100%;
  height: 100%;
  position: relative;
}

.dnd-flow .vue-flow-wrapper {
  flex-grow: 1;
  height: 100%;
}

@media screen and (min-width: 640px) {
  .dnd-flow {
    flex-direction: row;
  }
}

.dropzone-background {
  position: relative;
  height: 100%;
  width: 100%;
}

:deep(.vue-flow__node-input) {
  width: 100px;
  height: 60px;
  background: #2b3d6c !important;
  background-color: #2b3d6c !important;
  color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-color: rgba(255, 255, 255, 0.1);
}

:deep(.vue-flow__node-output) {
  width: auto;
  background: #2b3d6c !important;
  background-color: #2b3d6c !important;
  padding: 20px;
  color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-color: rgba(255, 255, 255, 0.1);
}

:deep(.vue-flow__node-default) {
  width: auto;
  background: #2b3d6c !important;
  background-color: #2b3d6c !important;
  padding: 20px;
  color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-color: rgba(255, 255, 255, 0.1);
}

:deep(.vue-flow__handle) {
  width: 8px;
  height: 8px;
  background-color: #2b3d6c;
  border: 1px solid #fff;
  opacity: 1 !important;
}

:deep(.vue-flow__handle-connecting) {
  background: #ff6b6b;
}

:deep(.vue-flow__handle-valid) {
  background: #55dd99;
}

:deep(.vue-flow__handle-bottom) {
  display: none !important;
}

:deep(.vue-flow__edge-path) {
  stroke: #2b3d6c;
  stroke-width: 2;
}

:deep(.vue-flow__edge.selected) {
  .vue-flow__edge-path {
    stroke: #00ff00;
  }
}

:deep(.vue-flow__node-default.selected),
:deep(.vue-flow__node-default.selected:hover),
:deep(.vue-flow__node-output.selected),
:deep(.vue-flow__node-output.selected:hover),
:deep(.vue-flow__node-output:focus),
:deep(.vue-flow__node-output:focus-visible),
:deep(.vue-flow__node-default:focus),
:deep(.vue-flow__node-default:focus-visible) {
  border: 1px solid #409EFF;
  border-color: #409EFF;
  box-shadow: 0 0 0 0.5px #409EFF;
}
</style>
